package com.wdh.monitor.service;

import com.mongodb.BasicDBObject;
import com.mongodb.client.*;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.wdh.monitor.cfg.MongoProperties;
import com.wdh.monitor.dto.MonitorDto;
import com.wdh.monitor.dto.MonitorReqDto;
import com.wdh.monitor.dto.MonitorStatisticsDto;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MonitorMongoService {

    private static final ExecutorService executorService = Executors.newFixedThreadPool(2);

    private MongoClient mongoClient;

    private MongoProperties mongoProperties;

    public static final String DB_NAME = "db_monitor";

    public static final String COLL_NAME = "t_monitor";

    public MonitorMongoService(MongoProperties mongoProperties){
        this.mongoProperties = mongoProperties;
        mongoClient = MongoClients.create(mongoProperties.getUrl());
    }


    /**
     * 采取队列的方式，改为批量插入
     * */
    public void insert(final MonitorDto monitorDto){
        executorService.submit(() -> {
            DateFormat dateFormat1 = new SimpleDateFormat("yyyyMMdd");
            DateFormat dateFormat2 = new SimpleDateFormat("yyyyMMddHH");
            MongoCollection<Document> collection = mongoClient.getDatabase(DB_NAME).getCollection(COLL_NAME);
            long startTime = monitorDto.getStartTime();
            Date startDate = new Date(startTime);
            Integer runDay = Integer.valueOf(dateFormat1.format(startDate));
            Integer runHour = Integer.valueOf(dateFormat2.format(startDate));
            long responseTime =  monitorDto.getEndTime() - startTime;
            Document doc = new Document();
            doc.append("startTime", startTime)
                    .append("endTime",monitorDto.getEndTime())
                    .append("responseTime",responseTime)
                    .append("runDay",runDay)
                    .append("runHour",runHour)
                    .append("exp",monitorDto.isExp())
                    .append("monitorName",monitorDto.getMonitorName())
                    .append("appName",mongoProperties.getAppName())
                    .append("timestamp",System.currentTimeMillis());
            collection.insertOne(doc);
        });
    }

    /**
     * 统计某接口指标
     * 没有测试，先这样吧，不弄了。。。
     * */
    public MonitorStatisticsDto getStatistics(MonitorReqDto reqDto){
        MonitorStatisticsDto dto = new MonitorStatisticsDto();
        Bson match = Filters.and(Filters.eq("appName", reqDto.getAppName()),
                Filters.eq("monitorName", reqDto.getMonitorName()),
                Filters.gte("startTime", reqDto.getStartTime()),
                Filters.lte("startTime", reqDto.getEndTime()));

        Bson group = Aggregates.group(null,
                Accumulators.max("maxTime", "$responseTime"),
                Accumulators.min("minTime", "$responseTime"),
                Accumulators.sum("reqNum", new BasicDBObject("$sum", 1)),
                Accumulators.sum("totalTime", new BasicDBObject("$sum", "$responseTime")));

        MongoCollection<Document> collection = mongoClient.getDatabase(DB_NAME).getCollection(COLL_NAME);
        MongoCursor<Document> iterator = collection.aggregate(Arrays.asList(Aggregates.match(match), group)).iterator();
        while (iterator.hasNext()){
            Document doc = iterator.next();
            Integer maxTime = doc.getInteger("maxTime");
            Integer minTime = doc.getInteger("minTime");
            Integer reqNum = doc.getInteger("reqNum");
            Long totalTime = doc.getLong("totalTime");

            Integer avgRt = new Long(totalTime / reqNum).intValue();

            dto.setMinRt(minTime);
            dto.setMaxRt(maxTime);
            dto.setReqNum(reqNum);
            dto.setAvgRt(avgRt);
        }
        return dto;
    }

}
